package cn.blnp.net.flowable.event.start.message;

import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.util.HashMap;

/**
 * <h3>开始事件-消息开始事件</h3>
 *
 * @author <a href="mailto:blnp.yibin@qq.com">lyb</a>
 * @version 1.0
 * @since 2025/5/7 14:51
 */
@Slf4j
@SpringBootTest
public class MessageEventTest {

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private TaskService taskService;

    /**
     *  <p>
     *      消息开始事件在接收到特定的消息后被触发，发起一个流程实例。定义格式如下所示：
     *  </p>
     *  <pre>
     *      {@code
     *          <!-- 定义消息 -->
     *          <message id="theMessage" name="newMessageName" />
     *          <process id="messageStartEventProcess">
     *              <!-- 定义开始节点 -->
     *              <startEvent id="messageStart" >
     *                  <!-- 包含 messageEventDefinition子元素，代表消息开始事件 -->
     *                  <messageEventDefinition messageRef="theMessage" />
     *              </startEvent>
     *              <!-- 其他元素省略 -->
     *          </process>
     *      }
     *  </pre>
     *  <p>
     *      触发API详见下文。需留意参数messageName是messageEventDefinition的messageRef属性引用的message元素的name属性。使用这些API需要注意以下事项。
     *  </p>
     *  <ul>
     *      <li>如果流程定义中有多个消息开始事件，那么startProcessInstanceByMessage()系列方法会选择对应的开始事件。</li>
     *      <li>如果流程定义中既有消息开始事件又有一个空开始事件，那么startProcessInstanceByKey()方法和startProcessInstanceById()方法会使用空开始事件发起流程实例。</li>
     *      <li>如果流程定义中有多个消息开始事件，而没有空开始事件，那么startProcessInstanceByKey()方法和startProcessInstanceById()方法会抛出异常。</li>
     *      <li>如果流程定义中只有一个消息开始事件，那么startProcessInstanceByKey()方法和startProcessInstanceById()方法会通过这个消息开始事件发起流程实例。</li>
     *      <li>如果被启动的流程是一个调用活动（call activity）并且有多个开始事件，那么该流程定义中除了含有消息开始事件，还需要含有一个空开始事件；或者该调用活动中只有一个消息开始事件。</li>
     *  </ul>
     **/
    @Test
    public void test() {
        //通过消息名称发起流程实例
        //runtimeService.startProcessInstanceByMessage(String messageName);

        //通过消息名称、租户ID发起流程实例
        runtimeService.startProcessInstanceByMessageAndTenantId("newMessageName", "tenantId");

        //通过消息名称、业务主键发起流程实例
        runtimeService.startProcessInstanceByMessage("newMessageName", "businessKey");

        //通过消息名称、业务主键和租户ID发起流程实例
        runtimeService.startProcessInstanceByMessageAndTenantId("newMessageName", "businessKey", "tenantId");

        //通过消息名称、流程变量发起流程实例
        runtimeService.startProcessInstanceByMessage(null, new HashMap<>());

        //通过消息名称、流程变量和租户ID发起流程实例
        runtimeService.startProcessInstanceByMessageAndTenantId(null, new HashMap<>(), "tenantId");

        //通过消息名称、业务主键和流程变量发起流程实例
        runtimeService.startProcessInstanceByMessage(null, "businessKey", new HashMap<>());

        //通过消息名称、业务主键、流程变量和租户ID发起流程实例
        runtimeService.startProcessInstanceByMessageAndTenantId(null, "businessKey", new HashMap<>(), "tenantId");
    }

    /**
     * <p><b>用途:演示案例<b></p>
     * <p>流程定义：{@link flow/messageEventTest.bpmn20.xml}</p>
     * <p>流程预览图：</p><br/>
     * <img src="https://free4.yunpng.top/2025/05/07/681b087eab52a.png" /><br/>
     *
     * <h2 style="color:red;">注意事项：</h2>
     * <ol>
     *     <li>
     *         在一个流程定义中，消息开始事件引用的消息的名称必须是唯一的。如果流程定义中有两个及两个以上消息开始事件引用了同一个消息，或两个及两个以上消息开始事件引用了拥有相同名称的消息，
     *     Flowable部署流程定义时会抛出异常。
     *     </li>
     *     <li>
     *         在所有已部署的流程定义中，消息开始事件引用的消息的名称必须是唯一的。如果在流程定义中，一个或多个消息开始事件引用了已经部署的另一流程定义中消息开始事件的消息名称，
     *     则Flowable会在部署该流程定义时抛出异常。
     *     </li>
     *     <li>
     *         在发布新版流程定义时，会取消上一版本的消息订阅，即使在新版本中并没有该消息事件。
     *     </li>
     *     <li>
     *         只有顶级流程（top-level process）才支持消息开始事件，内嵌子流程不支持消息开始事件。如果流程被调用活动启动，消息开始事件只支持以下两种情况：
     *         <ul>
     *             <li>在消息开始事件以外，还有一个单独的空开始事件</li>
     *             <li>流程只有一个消息开始事件，没有空开始事件。</li>
     *         </ul>
     *     </li>
     * </ol>
     * @author <a href="mailto:blnp.yibin@qq.com">lyb</a>
     * @since 15:11 2025/5/7
     * @params []
     * @param
     * @return void
    **/
    @Test
    public void test1() {
        Deployment deploy = repositoryService.createDeployment()
                .name("消息开始事件案例")
                .addClasspathResource("flow/messageEventTest.bpmn20.xml")
                .deploy();
        log.info("部署成功，流程ID：{}", deploy.getId());
        // 启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByMessage("dataReportingMessage");
        log.info("流程实例ID：{}", processInstance.getId());
        //查询此时的任务信息
        taskService.createTaskQuery()
                .processInstanceId(processInstance.getId())
                .list()
                .forEach(task -> {
            log.info("任务ID：{}", task.getId());
            log.info("任务名称：{}", task.getName());
            log.info("任务描述：{}", task.getDescription());
            log.info("任务创建时间：{}", task.getCreateTime());
            log.info("任务办理人：{}", task.getAssignee());
            log.info("流程实例ID：{}", task.getProcessInstanceId());
            log.info("流程定义ID：{}", task.getProcessDefinitionId());
        });

        /**
         *  演示结果：
         * 2025-05-07 15:26:00.799  INFO 93016 --- [           main] c.b.n.f.e.s.message.MessageEventTest     : 部署成功，流程ID：868727e8-2b14-11f0-b15c-50ebf6ec8f6d
         * 2025-05-07 15:26:00.857  INFO 93016 --- [           main] c.b.n.f.e.s.message.MessageEventTest     : 流程实例ID：86b84a0d-2b14-11f0-b15c-50ebf6ec8f6d
         * 2025-05-07 15:26:00.867  INFO 93016 --- [           main] c.b.n.f.e.s.message.MessageEventTest     : 任务ID：86bc68c2-2b14-11f0-b15c-50ebf6ec8f6d
         * 2025-05-07 15:26:00.867  INFO 93016 --- [           main] c.b.n.f.e.s.message.MessageEventTest     : 任务名称：数据上报
         * 2025-05-07 15:26:00.867  INFO 93016 --- [           main] c.b.n.f.e.s.message.MessageEventTest     : 任务描述：null
         * 2025-05-07 15:26:00.867  INFO 93016 --- [           main] c.b.n.f.e.s.message.MessageEventTest     : 任务创建时间：Wed May 07 15:26:00 CST 2025
         * 2025-05-07 15:26:00.870  INFO 93016 --- [           main] c.b.n.f.e.s.message.MessageEventTest     : 任务办理人：安琪拉
         * 2025-05-07 15:26:00.870  INFO 93016 --- [           main] c.b.n.f.e.s.message.MessageEventTest     : 流程实例ID：86b84a0d-2b14-11f0-b15c-50ebf6ec8f6d
         * 2025-05-07 15:26:00.870  INFO 93016 --- [           main] c.b.n.f.e.s.message.MessageEventTest     : 流程定义ID：messageEventTest:2:86b2f2db-2b14-11f0-b15c-50ebf6ec8f6d
         **/
    }
}
